package com.common.service.judicialpersonal.impl;

import com.common.constants.Constants;
import com.common.converter.CheckEvaluateConverter;
import com.common.converter.PersonalInfoConverter;
import com.common.entity.department.QDepartmentEntity;
import com.common.entity.evaluate.CheckEvaluateEntity;
import com.common.entity.evaluate.QCheckEvaluateEntity;
import com.common.entity.personal.PersonalEntity;
import com.common.entity.personal.QPersonalEntity;
import com.common.entity.system.DictionaryEntity;
import com.common.entity.user.UserEntity;
import com.common.global.BizException;
import com.common.global.BizServiceEnum;
import com.common.global.CommonEnum;
import com.common.query.QueryConditionVo;
import com.common.repository.judicialcheck.JudicialTargetTypeSumCheckRepository;
import com.common.repository.judicialpersonal.PersonalRepository;
import com.common.repository.system.DictionaryRepository;
import com.common.repository.user.UserRepository;
import com.common.requestvo.judicialpersonal.JudicialPersonalReqVo;
import com.common.service.judicialpersonal.JobExperienceService;
import com.common.service.judicialpersonal.JudicialPersonalService;
import com.common.utils.ChinseToPinyinUtils;
import com.common.vo.DateUtils;
import com.common.vo.evaluate.CheckEvaluateVo;
import com.common.vo.judicialpersonal.*;
import com.querydsl.core.QueryResults;
import com.querydsl.core.Tuple;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * 司法人员 个人档案 Service
 *
 * @author johnny
 * @create 2021-05-13 5:06 下午
 **/
@Service
@Slf4j
@Transactional(rollbackOn = Exception.class)
public class JudicialPersonalServiceImpl implements JudicialPersonalService {

    private final JPAQueryFactory queryFactory;

    private final JobExperienceService jobExperienceService;

    private final PersonalRepository personalRepository;

    private final UserRepository userRepository;

    private final DictionaryRepository dictionaryRepository;


    private final JudicialTargetTypeSumCheckRepository judicialTargetTypeSumCheckRepository;

    private final ThreadPoolTaskExecutor executor;

    Pattern pattern = Pattern.compile(".*[0-9]*");

    @Value("${systemParameters.init.password}")
    private String initPassword;


    public JudicialPersonalServiceImpl(JPAQueryFactory queryFactory, JobExperienceService jobExperienceService, PersonalRepository personalRepository, UserRepository userRepository, DictionaryRepository dictionaryRepository, JudicialTargetTypeSumCheckRepository judicialTargetTypeSumCheckRepository, ThreadPoolTaskExecutor executor) {
        this.queryFactory = queryFactory;
        this.jobExperienceService = jobExperienceService;
        this.personalRepository = personalRepository;
        this.userRepository = userRepository;
        this.dictionaryRepository = dictionaryRepository;
        this.judicialTargetTypeSumCheckRepository = judicialTargetTypeSumCheckRepository;
        this.executor = executor;
    }


    @Override
    public Page<JudicialPersonalVo> listByCondition(JudicialPersonalReqVo judicialPersonalReqVo, Pageable pageable) {

        List<JudicialPersonalVo> list = new ArrayList<>();
        QPersonalEntity qPersonalEntity = QPersonalEntity.personalEntity;
        QCheckEvaluateEntity qCheckEvaluateEntity = QCheckEvaluateEntity.checkEvaluateEntity;

        JPAQuery<Tuple> jpaQuery = queryFactory.select(qPersonalEntity, qCheckEvaluateEntity)
                .from(qPersonalEntity)
                .leftJoin(qCheckEvaluateEntity).on(qCheckEvaluateEntity.id.eq(qPersonalEntity.checkEvaluateId))
                .offset(pageable.getPageNumber() * pageable.getPageSize())
                .limit(pageable.getPageSize());

        fillCondition(jpaQuery, judicialPersonalReqVo);
        QueryResults<Tuple> queryResults = jpaQuery.fetchResults();

        queryResults.getResults().forEach(tuple -> {
            PersonalEntity personalInfo = tuple.get(0, PersonalEntity.class);
            JudicialPersonalVo judicialPersonalVo = PersonalInfoConverter.INSTANCE.domain2vo(personalInfo);
            CheckEvaluateEntity checkEvaluateEntity = tuple.get(1, CheckEvaluateEntity.class);
            if (checkEvaluateEntity != null) {
                judicialPersonalVo.setCheckEvaluateVo(CheckEvaluateConverter.INSTANCE.domain2vo(checkEvaluateEntity));
            } else {
                judicialPersonalVo.setCheckEvaluateVo(new CheckEvaluateVo());
            }
            list.add(judicialPersonalVo);
        });
        return new PageImpl<>(list, pageable, queryResults.getTotal());
    }

    /**
     * 根据 个人档案ID 查询 业务岗位说明
     * <p>
     * 业务岗位说明由 业务岗位经历  +  检察官职务及等级变更情况 + 岗位说明说  组成
     *
     * @param personalId
     * @return
     */
    @Override
    public JudicialPersonalDetailVo findBusinessJobDetail(Long personalId) {
        //业务岗位经历
        List<BusinessJobExperienceVo> businessJobExperienceVoList =
                jobExperienceService.findBusinessJobExperiencesByPersonalId(personalId, Constants.ASC);
        //检察官职务及等级变更情况
        List<JobChangeExperienceVo> jobChangeExperienceVoList =
                jobExperienceService.findJobChangeExperienceByPersonalId(personalId, Constants.ASC);
        //岗位说明说
        JobExplainVo jobExplainVo = jobExperienceService.findJobExperience(personalId);

        JudicialPersonalDetailVo judicialPersonalDetailVo = new JudicialPersonalDetailVo();
        judicialPersonalDetailVo.setBusinessJobExperienceVoList(businessJobExperienceVoList);
        judicialPersonalDetailVo.setJobChangeExperienceVoList(jobChangeExperienceVoList);
        judicialPersonalDetailVo.setJobExplainVo(jobExplainVo);

        return judicialPersonalDetailVo;
    }

    /**
     * 新增 个人档案
     *
     * @param judicialPersonalVo
     */
    @Override
    public void add(JudicialPersonalVo judicialPersonalVo) {
        judicialPersonalVo.setId(null);
        if (StringUtils.isEmpty(judicialPersonalVo.getName())) {
            throw new BizException(BizServiceEnum.NAME_IS_NULL);
        }

        PersonalEntity personalEntity = PersonalInfoConverter.INSTANCE.vo2domain(judicialPersonalVo);
        personalRepository.save(personalEntity);

        //初始化账号
        executor.execute(() -> {
            List<DictionaryEntity> dicList = dictionaryRepository.findByType(Constants.INIT_PASSWORD);
            if (CollectionUtils.isNotEmpty(dicList)) {
                DictionaryEntity dictionaryEntity = dicList.get(0);
                initPassword = dictionaryEntity.getValue();
            }
            UserEntity userEntity = new UserEntity();
            userEntity.setPersonalId(personalEntity.getId());
            userEntity.setPassword(initPassword);
            String pingYinUsername = ChinseToPinyinUtils.getPingYin(personalEntity.getName());
            if (userRepository.countByUsername(pingYinUsername) > 0) {
                //TODO 当多个重命 情况 暂时不写了。。
                //if (pattern.matcher(pingYinUsername).matches()) {
                pingYinUsername = pingYinUsername + "1";
                //}
            }
            userEntity.setUsername(pingYinUsername);
            userEntity.setHeadImage(judicialPersonalVo.getHeadImage());
            userEntity.setGender(Integer.valueOf(judicialPersonalVo.getGender()));
            userEntity.setRealName(judicialPersonalVo.getName());
            userEntity.setEnable(false);
            userEntity.setCreateBy(judicialPersonalVo.getCreateBy());
            userRepository.save(userEntity);
        });
    }


    /**
     * 编辑 个人档案
     *
     * @param judicialPersonalVo
     */
    @Override
    public void edit(JudicialPersonalVo judicialPersonalVo) {
        if (judicialPersonalVo.getId() != null) {
            PersonalEntity existPersonalEntity = personalRepository.findById(judicialPersonalVo.getId()).orElse(null);
            if (existPersonalEntity != null) {
                PersonalEntity personalEntity = PersonalInfoConverter.INSTANCE.vo2domain(judicialPersonalVo);
                personalRepository.save(personalEntity);
            } else {
                throw new BizException(CommonEnum.ID_NOT_FIND_ENTITY);
            }
        } else {
            throw new BizException(CommonEnum.ID_NOT_NULL);
        }
    }

    /**
     * 删除 个人档案
     *
     * @param id
     */
    @Override
    public void delete(Long id) {
        if (personalRepository.existsById(id)) {
            personalRepository.deleteById(id);
        } else {
            throw new BizException(CommonEnum.ID_NOT_FIND_ENTITY);
        }

    }

    /**
     * 批量删除 个人档案
     *
     * @param ids
     */
    @Override
    public void deletes(List<Long> ids) {
        boolean flag = true;
        for (Long id : ids) {
            if (!personalRepository.existsById(id)) {
                flag = false;
                break;
            }
        }
        if (flag) {
            personalRepository.deleteByIdIn(ids);
        }
    }

    @Override
    public void fillCondition(JPAQuery<Tuple> jpaQuery, QueryConditionVo queryConditionVo) {
        QPersonalEntity qPersonalEntity = QPersonalEntity.personalEntity;
        JudicialPersonalReqVo judicialPersonalReqVo = (JudicialPersonalReqVo) queryConditionVo;
        if (StringUtils.isNotEmpty(judicialPersonalReqVo.getName())) {
            jpaQuery.where(qPersonalEntity.name.like("%" + judicialPersonalReqVo.getName() + "%"));
        }
        if (judicialPersonalReqVo.getDepartmentId() != null && judicialPersonalReqVo.getDepartmentId() != 0L) {
            QDepartmentEntity qDepartmentEntity = QDepartmentEntity.departmentEntity;
            jpaQuery.leftJoin(qDepartmentEntity).on(qDepartmentEntity.id.eq(qPersonalEntity.departmentId));
            jpaQuery.where(qDepartmentEntity.id.eq(judicialPersonalReqVo.getDepartmentId()));
        }
        if (StringUtils.isNotEmpty(judicialPersonalReqVo.getPersonCategoryType())) {
            jpaQuery.where(qPersonalEntity.personCategoryType.eq(judicialPersonalReqVo.getPersonCategoryType()));
        }

        if (StringUtils.isNotEmpty(judicialPersonalReqVo.getLegalJob())) {
            jpaQuery.where(qPersonalEntity.legalJob.eq(judicialPersonalReqVo.getLegalJob()));
        }
        if (StringUtils.isNotEmpty(judicialPersonalReqVo.getProsecutorRank())) {
            jpaQuery.where(qPersonalEntity.prosecutorRank.eq(judicialPersonalReqVo.getProsecutorRank()));
        }
        if (StringUtils.isNotEmpty(judicialPersonalReqVo.getStartTimeToWork()) && StringUtils.isNotEmpty(judicialPersonalReqVo.getEndTimeToWork())) {
            jpaQuery.where(qPersonalEntity.timeToWork.between(DateUtils.formatDate(judicialPersonalReqVo.getStartTimeToWork(), DateUtils.DATE_YEAR_MONTH_SIMPLE_FORMAT),
                    DateUtils.formatDate(judicialPersonalReqVo.getEndTimeToWork(), DateUtils.DATE_YEAR_MONTH_SIMPLE_FORMAT)));
        }
        if (StringUtils.isNotEmpty(judicialPersonalReqVo.getStartTimeToJoinPart()) && StringUtils.isNotEmpty(judicialPersonalReqVo.getEndTimeToJoinPart())) {
            jpaQuery.where(qPersonalEntity.timeToJoinPart.between(DateUtils.formatDate(judicialPersonalReqVo.getStartTimeToJoinPart(), DateUtils.DATE_YEAR_MONTH_SIMPLE_FORMAT),
                    DateUtils.formatDate(judicialPersonalReqVo.getEndTimeToJoinPart(), DateUtils.DATE_YEAR_MONTH_SIMPLE_FORMAT)));
        }
        if (StringUtils.isNotEmpty(judicialPersonalReqVo.getStartTimeToProcurator()) && StringUtils.isNotEmpty(judicialPersonalReqVo.getEndTimeToProcurator())) {
            jpaQuery.where(qPersonalEntity.timeToProcurator.between(DateUtils.formatDate(judicialPersonalReqVo.getStartTimeToProcurator(), DateUtils.DATE_YEAR_MONTH_SIMPLE_FORMAT),
                    DateUtils.formatDate(judicialPersonalReqVo.getEndTimeToProcurator(), DateUtils.DATE_YEAR_MONTH_SIMPLE_FORMAT)));
        }


    }
}